import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Repository("${tableBean.tableNameNoDash}DAO")
public class ${tableBean.tableNameCapitalized}DAOImpl implements ${tableBean.tableNameCapitalized}DAO {
    private Logger log = Logger.getLogger(this.getClass());

    @Resource
    private JdbcTemplate jdbcTemplate${schemaName};

    @Override
    public ${tableBean.tableNameCapitalized} selectByPrimaryKey(Integer id) {
        try {
            String sql = "select * from ${tableBean.tableName} where id = ?";

            List<${tableBean.tableNameCapitalized}> resultList = this.jdbcTemplateMyWeb.query(sql, new Object[]{id},
                    (rs, rowNum) -> {
                        ${tableBean.tableNameCapitalized} bean = new ${tableBean.tableNameCapitalized}();
                        <#list tableBean.columnBeanList as columnBean>
                        bean.set${columnBean.columnNameCapitalized}(rs.${columnBean.columnTypeRsGetter}("${columnBean.columnName}"));
                        </#list>
                        return bean;
                    });

            if (null == resultList || resultList.isEmpty()) {
                return null;
            } else {
                return resultList.get(0);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<${tableBean.tableNameCapitalized}> selectByWhereSql(String whereSql, Object[] params) {
        try {
            String sql;
            if (StringUtils.isBlank(whereSql)) {
                sql = "select * from ${tableBean.tableName} ";
            } else {
                sql = "select * from ${tableBean.tableName} where " + whereSql;
            }

            return this.jdbcTemplateMyWeb.query(sql, params,
                    (rs, rowNum) -> {
                        ${tableBean.tableNameCapitalized} bean = new ${tableBean.tableNameCapitalized}();
                        <#list tableBean.columnBeanList as columnBean>
                        bean.set${columnBean.columnNameCapitalized}(rs.${columnBean.columnTypeRsGetter}("${columnBean.columnName}"));
                        </#list>
                        return bean;
                    });
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<${tableBean.tableNameCapitalized}> selectByWhereSql(String whereSql, Object[] params, int startPos, int num) {
        try {
            String sql;
            if (StringUtils.isBlank(whereSql)) {
                sql = "select * from ${tableBean.tableName} ";
            } else {
                sql = "select * from ${tableBean.tableName} where " + whereSql;
            }

            sql += String.format(" limit %d,%d", startPos, num);

            return this.jdbcTemplateMyWeb.query(sql, params,
                    (rs, rowNum) -> {
                        ${tableBean.tableNameCapitalized} bean = new ${tableBean.tableNameCapitalized}();
                        <#list tableBean.columnBeanList as columnBean>
                        bean.set${columnBean.columnNameCapitalized}(rs.${columnBean.columnTypeRsGetter}("${columnBean.columnName}"));
                        </#list>
                        return bean;
                    });
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<${tableBean.tableNameCapitalized}> selectAll() {
        return selectByWhereSql(null, null);
    }

    @Override
    public int count(String whereSql, Object[] params) {
        try {
            String sql;
            if (StringUtils.isBlank(whereSql)) {
                sql = "select count(1) numCount from ${tableBean.tableName} ";
            } else {
                sql = "select count(1) numCount from ${tableBean.tableName} where " + whereSql;
            }

            return this.jdbcTemplateMyWeb.queryForObject(sql, params,
                    (rs, rowNum) -> rs.getInt("numCount"));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public int insertSelective(${tableBean.tableNameCapitalized} ${tableBean.tableNameNoDash}) {
        try {
            if (null == ${tableBean.tableNameNoDash}) {
                return 0;
            }

            StringBuilder sql = new StringBuilder("insert into ${tableBean.tableName}(");
            List<Object> columns = new ArrayList<>();
            List<Object> values = new ArrayList<>();

            <#list tableBean.columnBeanList as columnBean>
            if (null != ${tableBean.tableNameNoDash}.get${columnBean.columnNameCapitalized}()) {
                columns.add("${columnBean.columnName}");
                values.add(${tableBean.tableNameNoDash}.get${columnBean.columnNameCapitalized}());
            }
            </#list>

            if (columns.isEmpty()) {
                return 0;
            }

            sql.append(StringUtils.join(columns, ',')).append(") values (");

            List<String> questions = columns.stream().map(o -> "?").collect(Collectors.toList());
            sql.append(StringUtils.join(questions, ',')).append(")");

            return jdbcTemplateMyWeb.update(sql.toString(), values.toArray());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public int updateByPrimaryKeySelective(${tableBean.tableNameCapitalized} ${tableBean.tableNameNoDash}) {
        try {
            if (null == ${tableBean.tableNameNoDash}.getId()) {
                throw new RuntimeException("updateByPrimaryKeySelective fail! ID can not be null");
            }

            StringBuilder sql = new StringBuilder("UPDATE ${tableBean.tableName} SET ");

            List<String> updateSql = new ArrayList<>();
            List<Object> params = new ArrayList<>();
            <#list tableBean.columnBeanList as columnBean>
            if (null != ${tableBean.tableNameNoDash}.get${columnBean.columnNameCapitalized}()) {
                updateSql.add("${columnBean.columnName} = ?");
                params.add(${tableBean.tableNameNoDash}.get${columnBean.columnNameCapitalized}());
            }
            </#list>

            if (updateSql.isEmpty()) { // all fields is null, nothing to update
                return 0;
            }

            sql.append(StringUtils.join(updateSql, ", ")).append(" WHERE id = ?");
            params.add(${tableBean.tableNameNoDash}.getId());

            return this.jdbcTemplateMyWeb.update(sql.toString(), params.toArray());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    @Override
        public int deleteByPrimaryKey(Integer id) {
            if(null == id) {
            return 0;
        }

        String sql = "delete from ${tableBean.tableName} where id = ?";
        return jdbcTemplateMyWeb.update(sql, id);
    }
}
